Skip to content

feat(api): add ListStageSummaries and WatchStageSummaries RPCs#6159

Draft
jacobboykin wants to merge 4 commits intoakuity:mainfrom
jacobboykin:jboykin/stage-summary-api
Draft

feat(api): add ListStageSummaries and WatchStageSummaries RPCs#6159
jacobboykin wants to merge 4 commits intoakuity:mainfrom
jacobboykin:jboykin/stage-summary-api

Conversation

@jacobboykin
Copy link
Copy Markdown
Member

Summary

Adds a lightweight Stage projection for clients rendering list and graph views of many Stages at once. The summary includes Stage metadata and current-state fields but omits heavier fields that are only needed when inspecting a single Stage in detail (full FreightHistory, PromotionTemplate step configuration, and Verification configuration). Use the existing GetStage endpoint when detail fields are needed.

API

  • ConnectRPC: ListStageSummaries(ListStageSummariesRequest) and WatchStageSummaries(WatchStageSummariesRequest)
  • REST: GET /v1beta1/projects/{project}/stage-summaries (supports ?watch=true for SSE)

Request options on both list and watch:

  • freightOrigins (repeated string): restrict results to Stages that request Freight originating from the named Warehouse(s).
  • resourceVersion (string): optional Kubernetes ResourceVersion for the standard list-then-watch pattern. ListStageSummaries returns the list's resourceVersion in its response so clients can pass it to WatchStageSummaries and resume from that point.

Test plan

  • Unit tests for the stageToSummary conversion helper (nil, minimal, fully-populated, empty FreightHistory, nil PromotionTemplate, nil Verification, isolation from source mutation).
  • Unit tests for the ConnectRPC ListStageSummaries handler including freightOrigins filter cases.
  • Unit tests for the REST list and watch endpoints.
  • make test-unit passes.
  • make lint-go is clean.

Adds a lightweight Stage projection for list and graph views that need
metadata and current state for many Stages at once but do not need the
full Stage CR. The summary omits FreightHistory entries beyond the
current FreightCollection, PromotionTemplate step configuration, and
Verification configuration. Use GetStage to retrieve the full Stage
resource when detail fields are needed.

Both endpoints are available in ConnectRPC and REST
(GET /v1beta1/projects/{project}/stage-summaries, including
?watch=true for SSE). Requests accept an optional freightOrigins
filter and a resourceVersion for the standard list-then-watch pattern.

Signed-off-by: Jacob Boykin <boykinmusic@gmail.com>
Signed-off-by: Jacob Boykin <jacob.boykin@akuity.io>
@netlify
Copy link
Copy Markdown

netlify Bot commented Apr 23, 2026

Deploy Preview for docs-kargo-io ready!

Name Link
🔨 Latest commit 7f4b033
🔍 Latest deploy log https://app.netlify.com/projects/docs-kargo-io/deploys/69eadc80c48db400093b5ff6
😎 Deploy Preview https://deploy-preview-6159.docs.kargo.io
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 23, 2026

Codecov Report

❌ Patch coverage is 67.64706% with 88 lines in your changes missing coverage. Please review.
✅ Project coverage is 57.63%. Comparing base (39f71ec) to head (7f4b033).

Files with missing lines Patch % Lines
pkg/server/watch_stage_summaries_v1alpha1.go 0.00% 44 Missing ⚠️
pkg/server/list_stage_summaries_v1alpha1.go 73.87% 19 Missing and 10 partials ⚠️
pkg/server/get_stage_health_outputs_v1alpha1.go 80.30% 9 Missing and 4 partials ⚠️
pkg/server/stage_to_summary.go 95.91% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #6159      +/-   ##
==========================================
+ Coverage   57.56%   57.63%   +0.06%     
==========================================
  Files         474      478       +4     
  Lines       40469    40741     +272     
==========================================
+ Hits        23296    23480     +184     
- Misses      15789    15862      +73     
- Partials     1384     1399      +15     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@jacobboykin
Copy link
Copy Markdown
Member Author

jacobboykin commented Apr 23, 2026

Some numbers from a local stress test (500 Stages in one project, 10 FreightHistory entries each, realistic freight / verification data populated):

Endpoint Wire size Latency Per item
GET /v1beta1/projects/:p/stages 22.32 MB ~100 ms warm 45.7 KB
GET /v1beta1/projects/:p/stage-summaries 3.72 MB ~55 ms 7.8 KB

~6× payload reduction, consistent with the fields the summary omits (freightHistory[1..], full PromotionTemplate.spec.steps, Verification).

JS heap impact from the browser, measured by fetching + JSON.parseing each response, holding the result, and diffing performance.memory.usedJSHeapSize:

Response Heap delta
ListStages (22 MB JSON) +48 MB
ListStageSummaries (3.7 MB JSON) +7.8 MB

~6× reduction in JS heap held by the parsed response, tracking the payload reduction linearly.

ListStages response is byte-identical between main and this branch (23,409,060 bytes both times) — no regression on the existing endpoint.

jacobboykin and others added 3 commits April 23, 2026 19:41
Buf lint enforces lower_snake_case for proto field names. Updated the
new StageSummary / ListStageSummaries / WatchStageSummaries messages
accordingly. Generated Go struct names (StageSummaries, FreightOrigins,
etc.) and protojson wire format (camelCase via the json= tag) are
unchanged. Swagger and TypeScript bindings regenerated to match.

Signed-off-by: Jacob Boykin <boykinmusic@gmail.com>
Signed-off-by: Jacob Boykin <jacob.boykin@akuity.io>
…geSummary

Adds a batch RPC that returns the raw health output blob for a specified
set of Stages in a project, and updates stageToSummary to always leave
Status.Health.Output nil in the summary response. Intended for clients
that use ListStageSummaries for the stage list and want to resolve
per-argocd-app health only for the Stages currently in viewport (React
Flow virtualizes to ~10-30 visible nodes at a time).

The raw health output is typically ~2 KB per Stage and is the single
largest remaining field in StageSummary. Moving it behind a lazy fetch
drops the summary to roughly 1-2 KB per stage, reducing both wire
transfer and the heap footprint of the cached list.

The new endpoint is available in ConnectRPC and REST
(GET /v1beta1/projects/{project}/stage-health-outputs?stageNames=a&stageNames=b).
Stages that do not exist or have no recorded health output are omitted
from the response map; the endpoint has best-effort semantics.

Signed-off-by: Jacob Boykin <boykinmusic@gmail.com>
Signed-off-by: Jacob Boykin <jacob.boykin@akuity.io>
Comment on lines +105 to +119
// @id ListStageSummaries
// @Summary List Stage Summaries
// @Description List a lightweight projection of Stage resources from a
// @Description project's namespace. Intended for UI list and graph views that
// @Description need metadata and current state for many Stages at once but do
// @Description not need full FreightHistory, PromotionTemplate steps, or
// @Description Verification configuration. Use GetStage for detail fields.
// @Tags Core, Project-Level
// @Security BearerAuth
// @Produce json
// @Param project path string true "Project name"
// @Param freightOrigins query []string false "Warehouse name(s) to filter by" collectionFormat(multi)
// @Success 200 {object} svcv1alpha1.ListStageSummariesResponse
// @Router /v1beta1/projects/{project}/stage-summaries [get]
func (s *server) listStageSummaries(c *gin.Context) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a defensible reason for this being a dedicated endpoint instead of just adding an optional summary=true query param to the existing endpoint, in which case, you'll just drop the fields that "summary" excludes?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants